/*********************************************************************
 *
 *              Application Programming Interface (API)
 *                     for COM-R04-S01b Module
 *
 *********************************************************************
 * FileName:        com_r04_s01b.c
 * Dependencies:    platform.h
 * Processor:       processor independent
 * Complier:        compiler independent
 * Company:         Budapest University of Technology and Economics
 * 					Department of Measurement and Information Systems
 * note:
 *
 *	General API for the COM-R04-S01b Mitmot module. This API use the
 * 	Mitmote BUS functions specified by the mcu API.
 *
 * Standard COM-R04-S01b is configured to 433MHz operation with 10MHz
 * xtal using a 12pF load. Also as typically is FIFO enabled operation
 * only mitmot GPIO13 and GPIO14 is used in addition to the SPI pins.
 * GPIO13 is for SPI slave select, and GPIO14 for the Interrupt signal
 * (nIRQ)
 *
 * Author               Date    Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Balazs Scherer     10/06/05   Original
 ********************************************************************/

#include "com_r04_s01b.h"
#include "platform.h"


/********************************************************************/
/*************        Internal functions       **********************/
/********************************************************************/

unsigned short update_crc(unsigned short crc, unsigned char *buf, int len);
unsigned short crc(unsigned char *buf, int len);

/********************************************************************/
/*************             Globals             **********************/
/********************************************************************/

unsigned char transfer_setting = 0x00;

/*********************************************************************/
/*********************************************************************/
/**********          Inicialisation, controll	      ****************/
/*********************************************************************/
/*********************************************************************/

/*********************************************************************
 * Function: 	  void com_r04_s01__Init_433 (void)
 *
 * PreCondition:  none
 *
 * Input:         unsigned int sub_frequency: The sub frequency band for RF
 * 					communication.
 * 				  unsigned char baseband_bw: Select the baseband BW
 * 					between 67kHz and 400 kHz
 * 				  unsigned char deviation: FSK deviation between 15kHz to 240 kHz
 * 				  unsigned char power: Relative output power. The maximum is about 8dBm
 * 				  unsigned char data_rate: setting the communication data rate
 *
 * Output:        none
 *
 * Side Effects:  1, Inicialisation of the SPI interface, and the
 * 				  	 GPIO pins used by the com-r04 module
 * 				  2, Setting the Configuration setting to 433 MHz
 * 					 main band, 12pF load and enabling Tx data register
 * 					 Rx FIFO.
 * 				  3, Setting up the sub bands to the 433.050 - 434.790 MHz
 * 					 ISM bands using the com_r04_s01__Set_Sub_Frequency.
 * 				  4, Enabling the synthesier and the oscillator in the
 * 					 power management register
 * 				  5, Setting baseband BW with com_r04_s01__Set_Baseband_BW
 * 				  6, Setting the deviation with com_r04_s01__Set_Deviation
 * 				  7, Setting the Relative output power with
 * 					 com_r04_s01__Set_Relative_Output_power
 * 				  8, Setting the data rate with com_r04_s01__Set_Data_rate
 *
 * Overview:      Call the appropriate MCU api functions for
 * 				  PIN direction and SPI inicialisation.
 * 				  Then configurating the RF communication with the appropirate
 * 				  API functions
 *
 * Note:          USE PRE DEFINED PARAMETERS
  ********************************************************************/

void com_r04_s01__Init_433 (unsigned int sub_frequency, unsigned char baseband_bw, unsigned char deviation, unsigned char power, unsigned char data_rate)
{
  unsigned char data1,data2;

  /************/
  GPIO_13_DIR_OUTPUT();
  GPIO_14_DIR_INPUT();

#if ARM_LPC2106
	SPI_Init(0,0,0,100);
#elif AVR_ATMEGA128
	SPI_Init(0,0,0,4);
#endif


  // Configuration Setting command
  GPIO_13_CLEAR();
   SPI_byte(0x80,&data1);
   SPI_byte(0xD7,&data2);  // enables the internal data register, rx fifo, 433 MHz, 12 pF
  GPIO_13_SET();

   // Configuration Setting command again experiences shows that it should be done twice
  GPIO_13_CLEAR();
   SPI_byte(0x80,&data1);
   SPI_byte(0xD7,&data2);  // enables the internal data register, rx fifo, 433 MHz, 12 pF
  GPIO_13_SET();

  // Sub frequencies
  com_r04_s01__Set_Sub_Frequency(sub_frequency);

  // Power management command
  GPIO_13_CLEAR();
   SPI_byte(0x82,&data1);
   SPI_byte(0x18,&data2);
  GPIO_13_SET();   // syntheser, oscillator on

  // Setting baseband BW
  com_r04_s01__Set_Baseband_BW(baseband_bw);

  // Transmiter Controll command
  com_r04_s01__Set_Deviation (deviation);
  com_r04_s01__Set_Relative_Output_power (power);


  // Transmiter Controll command
  com_r04_s01__Set_Data_rate (data_rate);

  // dummy status read for power on reset acknowledgement
  com_r04_s01__Read_Status();

}




/*********************************************************************
 * Function: 	  void com_r04_s01__Set_Sub_Frequency (unsigned int frequency)
 *
 * PreCondition:  SPI, and GPIO inicialisation
 *
 * Input:         unsigned int frequency: The sub frequency band for RF
 * 					communication. Do not set operating frequency outside
 * 					the ISM bands. USE THE PRE DEFINED SUB BANDS.
 * 					(SUB_BAND_433_1_MHz for example)
 *
 * Output:        none
 *
 * Side Effects:  Setting the Frequency register in the IA4420.
 *
 * Overview:      Uses MCU api for SPI communication.
 *
 * Note:          Do not set operating frequency outside the ISM bands.
 * 				  USE THE PRE DEFINED SUB BANDS. (SUB_BAND_433_1_MHz for example)
  ********************************************************************/
void com_r04_s01__Set_Sub_Frequency (unsigned int frequency)
{
unsigned char d1,d2,data;

  // Frequency Setting command
  d1 = (unsigned char)((frequency & 0xFF00)>>8);
  d2 = (unsigned char)(frequency & 0x00FF);

  GPIO_13_CLEAR();
   SPI_byte(d1,&data);
   SPI_byte(d2,&data);
  GPIO_13_SET();

}


/*********************************************************************
 * Function: 	  void com_r04_s01__Set_Baseband_BW (unsigned char baseband)
 *
 * PreCondition:  SPI, and GPIO inicialisation
 *
 * Input:         unsigned char baseband: Select the baseband BW
 * 					between 67kHz and 400 kHz
 *
 * Output:        none
 *
 * Side Effects:  Setting the Baseband BW for receiver part and
 * 				  also setting the LNA max, VDI output, DRSSI -103 dBm
 *
 * Overview:      Uses MCU api for SPI communication.
 *
 * Note:          Use the pre defined values like BASEBAND_BW_400_kHz
  ********************************************************************/
void com_r04_s01__Set_Baseband_BW (unsigned char baseband)
{
unsigned char data;

  // Setting the baseband in Receiver controll

  GPIO_13_CLEAR();
   SPI_byte(0x96,&data);
   SPI_byte(baseband,&data);  // Setting LNA max, VDI output, DRSSI -103 dBm
  GPIO_13_SET();

}


/*********************************************************************
 * Function: 	  void com_r04_s01__Set_Deviation (unsigned char deviation)
 *
 * PreCondition:  SPI, and GPIO inicialisation
 *
 * Input:         unsigned char deviation: FSK deviation between 15kHz to 240 kHz
 *
 * Output:        none
 *
 * Side Effects:  Setting the FSK deviation between 15kHz to 240 kHz
 *
 * Overview:      Uses MCU api for SPI communication.
 *
 * Note:          Use pre defined values like FSK_DEVIATION_90_kHz
  ********************************************************************/
void com_r04_s01__Set_Deviation (unsigned char deviation)
{
unsigned char data;

  // Setting the deviation the bits 0 to 3 contains the PA values
  // we keeping them
  transfer_setting = ((transfer_setting & 0x0F) | deviation);

  GPIO_13_CLEAR();
   SPI_byte(0x98,&data);
   SPI_byte(transfer_setting,&data);
  GPIO_13_SET();

}


/*********************************************************************
 * Function: 	  void com_r04_s01__Set_Relative_Output_power (unsigned char power)
 *
 * PreCondition:  SPI, and GPIO inicialisation
 *
 * Input:         unsigned char power: Relative output power. The maximum is
 * 					about 8dBm
 *
 * Output:        none
 *
 * Side Effects:  Setting the relative output power
 *
 * Overview:      Uses MCU api for SPI communication.
 *
 * Note:          Use pre defined values like OUTPUT_POWER_MAX_minus_6dB
  ********************************************************************/
void com_r04_s01__Set_Relative_Output_power (unsigned char power)
{
unsigned char data;

  // Setting the deviation the bits 4 to 7 contains the deviation
  // values, therefore we keeping them
  transfer_setting = ((transfer_setting & 0xF0) | power);

  GPIO_13_CLEAR();
   SPI_byte(0x98,&data);
   SPI_byte(transfer_setting,&data);
  GPIO_13_SET();

}


/*********************************************************************
 * Function: 	  void com_r04_s01__Set_Data_rate (unsigned char data_rate)
 *
 * PreCondition:  SPI, and GPIO inicialisation
 *
 * Input:         unsigned char data_rate: setting the communication data rate
 *
 * Output:        none
 *
 * Side Effects:  Setting the data rate register
 *
 * Overview:      Uses MCU api for SPI communication.
 *
 * Note:          Use pre defined values like DATA_RATE_9600_bps
  ********************************************************************/
void com_r04_s01__Set_Data_rate (unsigned char data_rate)
{
unsigned char data;

 // Data rate register setting

  GPIO_13_CLEAR();
   SPI_byte(0xC6,&data);
   SPI_byte(data_rate,&data);
  GPIO_13_SET();

}



/*********************************************************************
 * Function: 	  unsigned int com_r04_s01__Read_Status (void)
 *
 * PreCondition:  SPI, and GPIO inicialisation
 *
 * Input:         none
 *
 * Output:        The 16bit status word of the IA4420
 *
 * Side Effects:  Reading the RF chip's status
 *
 * Overview:      Uses MCU api for SPI communication.
 *
 * Note:          none
  ********************************************************************/

unsigned int com_r04_s01__Read_Status (void)
{
	unsigned char data1,data2;
	unsigned int status;

 	GPIO_13_CLEAR();

//  Read status
	SPI_byte(0x00,&data1);
	SPI_byte(0x00,&data2);

	GPIO_13_SET();

 	status = (data1<<8)+data2;
	return status;
}


/*********************************************************************/
/*********************************************************************/
/*****************          Transmitting	          ****************/
/*********************************************************************/
/*********************************************************************/

/*********************************************************************
 * Function: 	  void com_r04_s01__Transmitter_Disable (void)
 *
 * PreCondition:  com_r04_s01__Init_433
 *
 * Input:         none
 *
 * Output:        none
 *
 * Side Effects:  Disabling the transmitter. The synthesier and the oscillator
 * 				  remains enabled.
 *
 * Overview:      Uses MCU api for SPI communication.
 *
 * Note:          Always disable transmitter after sending a packet, or the
 * 				  radio remains active and sends 0-s.
  ********************************************************************/

void com_r04_s01__Transmitter_Disable (void)
{
	unsigned char data;

	// Power management command
	GPIO_13_CLEAR();
	SPI_byte(0x82,&data);
	SPI_byte(0x18,&data);  // syntheser, oscillator on
	GPIO_13_SET();

}


/*********************************************************************
 * Function: 	  void com_r04_s01__Start_Transmitting (void)
 *
 * PreCondition:  com_r04_s01__Init_433
 *
 * Input:         none
 *
 * Output:        none
 *
 * Side Effects:  Disabling and then enabling the transmitter which starts
 * 				  transmitting the value in the TX register
 *
 * Overview:      Uses MCU api for SPI communication.
 *
 * Note:          none
  ********************************************************************/

void com_r04_s01__Start_Transmitting (void)
{
	unsigned char data;

	// Power management command
	GPIO_13_CLEAR();
   	  SPI_byte(0x82,&data);
	  SPI_byte(0x18,&data);  // disable transmitter
	GPIO_13_SET();

	// Power management command
	GPIO_13_CLEAR();
	  SPI_byte(0x82,&data);
	  SPI_byte(0x38,&data);  // enable transmitter
	GPIO_13_SET();

}


/*********************************************************************
 * Function: 	  void com_r04_s01__Write_Transmit_data (unsigned char d)
 *
 * PreCondition:  com_r04_s01__Init_433
 *
 * Input:         unsigned char d: 8bit data to transmit
 *
 * Output:        none
 *
 * Side Effects:  Writing the data to the transmit register
 *
 * Overview:      Uses MCU api for SPI communication.
 *
 * Note:          none
  ********************************************************************/

void com_r04_s01__Write_Transmit_data (unsigned char d)
{
	unsigned char data;

	// Transmit register write command
	GPIO_13_CLEAR();
   	  SPI_byte(0xB8,&data);
	  SPI_byte(d,&data);
	GPIO_13_SET();

}


/*********************************************************************
 * Function: 	  void com_r04_s01__Send_Packet (unsigned char* buffer, unsigned short int length)
 *
 * PreCondition:  com_r04_s01__Init_433
 *
 * Input:         unsigned char* buffer: pointer to the data to send
 * 				  unsigned short int length: the length of the data
 *
 * Output:        none
 *
 * Side Effects:  Sending the data using the RF link
 *
 * Overview:      1, Inicializating the Tx reg with 0xAA preamble
 * 				  2, Start the transmitting. com_r04_s01__Start_Transmitting()
 * 				  3, Sending 7 other 0xAA as preamble
 * 				  4, Sending the 0x2DD4 as syncron pattern
 * 				  5, Sending the packet length
 * 				  6, Sending the data
 * 				  7, Calculating and sending the CRC
 * 				  8, Disabling the transducer
 *
 * Note:          This function is a blocking one. After every byte send
 * 				  we are waiting for the TX register empty IT signal, and
 * 				  therefore if radio hardware error then the program
 * 				  execution is halted.
  ********************************************************************/

void com_r04_s01__Send_Packet (unsigned char* buffer, unsigned short int length)
{
unsigned int i,status1;
unsigned short int crc_value;

/*** Start transmitting ***/
	com_r04_s01__Write_Transmit_data (0xAA);
	com_r04_s01__Start_Transmitting();

/*** Sending preamble ***/
	while (GPIO_14_GET_VALUE());
	status1 = com_r04_s01__Read_Status();
	com_r04_s01__Write_Transmit_data (0xAA);
	while (GPIO_14_GET_VALUE());
	status1 = com_r04_s01__Read_Status();
	com_r04_s01__Write_Transmit_data (0xAA);
	while (GPIO_14_GET_VALUE());
	status1 = com_r04_s01__Read_Status();
	com_r04_s01__Write_Transmit_data (0xAA);
	while (GPIO_14_GET_VALUE());
	status1 = com_r04_s01__Read_Status();
	com_r04_s01__Write_Transmit_data (0xAA);
	while (GPIO_14_GET_VALUE());
	status1 = com_r04_s01__Read_Status();
	com_r04_s01__Write_Transmit_data (0xAA);
	while (GPIO_14_GET_VALUE());
	status1 = com_r04_s01__Read_Status();
	com_r04_s01__Write_Transmit_data (0xAA);
	while (GPIO_14_GET_VALUE());
	status1 = com_r04_s01__Read_Status();
	com_r04_s01__Write_Transmit_data (0xAA);

/*** Sending syncron pattern ***/
	while (GPIO_14_GET_VALUE());
	status1 = com_r04_s01__Read_Status();
	com_r04_s01__Write_Transmit_data (0x2D);
	while (GPIO_14_GET_VALUE());
	status1 = com_r04_s01__Read_Status();
	com_r04_s01__Write_Transmit_data (0xD4);

/*** Sending packet length ***/
	while (GPIO_14_GET_VALUE());
	status1 = com_r04_s01__Read_Status();
	com_r04_s01__Write_Transmit_data (((length&0xFF00)>>8));
	while (GPIO_14_GET_VALUE());
	status1 = com_r04_s01__Read_Status();
	com_r04_s01__Write_Transmit_data (length&0x00FF);

/*** Sending data ***/
	for(i=0;i<length;i++)
	{
		while (GPIO_14_GET_VALUE());
		status1 = com_r04_s01__Read_Status();
		com_r04_s01__Write_Transmit_data (buffer[i]);
	}

/*** Sending CRC ***/
	crc_value = crc(buffer,length);

	while (GPIO_14_GET_VALUE());
	status1 = com_r04_s01__Read_Status();
	com_r04_s01__Write_Transmit_data (((crc_value&0xFF00)>>8));
	while (GPIO_14_GET_VALUE());
	status1 = com_r04_s01__Read_Status();
	com_r04_s01__Write_Transmit_data (crc_value&0x00FF);

/*** Disabling the transmitter ***/
	while (GPIO_14_GET_VALUE());
	status1 = com_r04_s01__Read_Status();
	com_r04_s01__Write_Transmit_data (0x00);

	while (GPIO_14_GET_VALUE());
	status1 = com_r04_s01__Read_Status();
	com_r04_s01__Transmitter_Disable();
}



/*********************************************************************/
/*********************************************************************/
/*******************          Receiving	              ****************/
/*********************************************************************/
/*********************************************************************/

/*********************************************************************
 * Function: 	  void com_r04_s01__Enable_Receiver (void)
 *
 * PreCondition:  com_r04_s01__Init_433
 *
 * Input:         none
 *
 * Output:        none
 *
 * Side Effects:  Enabling the receiver path by enabling the receiver and
 * 				  baseband
 *
 * Overview:      Uses MCU api for SPI communication.
 *
 * Note:          none
  ********************************************************************/

void com_r04_s01__Enable_Receiver (void)
{
	unsigned char data;
	// Power management command

	GPIO_13_CLEAR();
   	SPI_byte(0x82,&data);
	SPI_byte(0xD8,&data);
	GPIO_13_SET();

}


/*********************************************************************
 * Function: 	  com_r04_s01__Disable_Receiver (void)
 *
 * PreCondition:  com_r04_s01__Init_433
 *
 * Input:         none
 *
 * Output:        none
 *
 * Side Effects:  Disabling the receiver path
 *
 * Overview:      Uses MCU api for SPI communication.
 *
 * Note:          none
  ********************************************************************/

void com_r04_s01__Disable_Receiver (void)
{
	unsigned char data;
	// Power management command

	GPIO_13_CLEAR();
		SPI_byte(0x82,&data);
		SPI_byte(0x18,&data);
	GPIO_13_SET();

}


/*********************************************************************
 * Function: 	  void com_r04_s01__Start_Receiving (void)
 *
 * PreCondition:  com_r04_s01__Init_433, com_r04_s01__Enable_Receiver
 *
 * Input:         none
 *
 * Output:        none
 *
 * Side Effects:  Disabling and then enabling the Synchron pattern recognition
 *
 * Overview:      Uses MCU api for SPI communication. For configurating the
 * 				  FIFO buffer register
 *
 * Note:          After enabling the synchron pattern recognition the IA4420
 * 				  will notify us if a 0x2DD4 is received by pulling down the
 * 				  nIRQ signal.
  ********************************************************************/

void com_r04_s01__Start_Receiving (void)
{
	unsigned char data1,data2;

	// FIFO buffer
	GPIO_13_CLEAR();
   	  SPI_byte(0xCA,&data1);
	  SPI_byte(0x80,&data2);  // Synchron pattern, disable patern recog
	GPIO_13_SET();

	// FIFO buffer
	GPIO_13_CLEAR();
   	  SPI_byte(0xCA,&data1);
	  SPI_byte(0x82,&data2);  // Synchron pattern, enable patern recog
	GPIO_13_SET();

}

/*********************************************************************
 * Function: 	  unsigned char com_r04_s01__Read_FIFO (void)
 *
 * PreCondition:  com_r04_s01__Init_433, com_r04_s01__Enable_Receiver,
 * 				  com_r04_s01__Start_Receiving
 *
 * Input:         none
 *
 * Output:        unsigned char: 8 bit data readed from the receive FIFO
 *
 * Side Effects:  Reading 8 bit data from the FIFO
 *
 * Overview:      Uses MCU api for SPI communication for reading the FIFO
 *
 *
 * Note:          none
  ********************************************************************/

unsigned char com_r04_s01__Read_FIFO (void)
{
	unsigned char data1,data2;

	// FIFO buffer
	 GPIO_13_CLEAR();
    	 SPI_byte(0xB0,&data1);
    	 SPI_byte(0x00,&data2);  // Pmax
	 GPIO_13_SET();

	return data2;
}


/*********************************************************************
 * Function: 	  unsigned char com_r04_s01__Receiving_Packet (unsigned char* buffer, unsigned short int* length)
 *
 * PreCondition:  com_r04_s01__Init_433
 *
 * Input:         unsigned char* buffer: pointer for the incomming data
 * 				  unsigned short int* length: the maximum length of the incomming packet
 *
 * Output:        unsigned char: COM_R04_S01__ERROR if the length of the incomming packet is
 * 								 greater than unsigned short int* length parameter. Or the
 * 								 received packet contains a CRC error.
 * 								 COM_R04_S01__NOERROR if the packet is received correctly
 *
 * 				  unsigned short int* length: the length of the received packet
 *
 * Side Effects:  Waiting for a packet to receive
 *
 * Overview:      1, Enabling the receiver path with com_r04_s01__Enable_Receiver()
 * 				  2, Starting the synchron patter recognition with com_r04_s01__Start_Receiving()
 * 				  3, Waiting for the synchron pattern THIS IS A BLOCKING PART WITHOUT A TIME LIMIT
 * 				  4, reading and comparing the length of the packet with the incomming length
 * 					 parameter. If the received length is greater than the specified maximum, then
 * 					 aborting the packet receive and signaling an error
 * 				  5, receiving the packet
 * 				  6, receiving and checking the CRC. If the CRC is not correct then
 * 					 aborting the packet receive and signaling an error
 * 				  7, Packed receive finished. Disabling the receiver
 *
 * Note:          This is a blocking function and waits until a packet is received
  ********************************************************************/
unsigned char com_r04_s01__Receiving_Packet (unsigned char* buffer, unsigned short int* length)
{
unsigned char d1,d2;
unsigned int len,i,status;
unsigned short int crc_value_r,crc_value_c;


	com_r04_s01__Enable_Receiver();
	com_r04_s01__Start_Receiving();

/*** waiting for syncron pattern ***/
	while (GPIO_14_GET_VALUE());
	status = com_r04_s01__Read_Status();
	d1 = com_r04_s01__Read_FIFO();

	while (GPIO_14_GET_VALUE());
	status = com_r04_s01__Read_Status();
	d2 = com_r04_s01__Read_FIFO();

	len = (d1<<8)+d2;

	if (len > *length)
		{
		 com_r04_s01__Disable_Receiver();
		 return COM_R04_S01__ERROR;
		}

	*length = len;

	for (i=0;i<len;i++)
	 {
		while (GPIO_14_GET_VALUE());
		status = com_r04_s01__Read_Status();
	 	buffer[i] = com_r04_s01__Read_FIFO();
	 }

	/*** Receiving CRC ***/
	while (GPIO_14_GET_VALUE());
	status = com_r04_s01__Read_Status();
	d1 = com_r04_s01__Read_FIFO();

	while (GPIO_14_GET_VALUE());
	status = com_r04_s01__Read_Status();
	d2 = com_r04_s01__Read_FIFO();

	crc_value_r = (d1<<8)+d2;
	crc_value_c = crc(buffer,len);

	if (crc_value_r!=crc_value_c)
		{
   		 com_r04_s01__Disable_Receiver();
		 return COM_R04_S01__ERROR;
		}

	com_r04_s01__Disable_Receiver();

	return COM_R04_S01__NOERROR;

}




/*********************************************************************
 * Function: 	  unsigned char com_r04_s01__Receiving_Packet_with_timeout (unsigned char* buffer, unsigned short int* length, unsigned short int timeout)
 *
 * PreCondition:  com_r04_s01__Init_433
 *
 * Input:         unsigned char* buffer: pointer for the incomming data
 * 				  unsigned short int* length: the maximum length of the incomming packet
 *				  unsigned short int timeout: Timeout in ms. (This is not a precise timeout only an approximetry one)
 *
 * Output:        unsigned char: COM_R04_S01__ERROR if the length of the incomming packet is
 * 								 greater than unsigned short int* length parameter. Or the
 * 								 received packet contains a CRC error.
 *								 COM_R04_S01__TIMEOUT if timeout occured
 * 								 COM_R04_S01__NOERROR if the packet is received correctly
 *
 * 				  unsigned short int* length: the length of the received packet
 *
 * Side Effects:  Waiting for a packet to receive with timeout
 *
 * Overview:      1, Enabling the receiver path with com_r04_s01__Enable_Receiver()
 * 				  2, Starting the synchron patter recognition with com_r04_s01__Start_Receiving()
 * 				  3, Waiting for the synchron pattern or timeout
 * 				  4, reading and comparing the length of the packet with the incomming length
 * 					 parameter. If the received length is greater than the specified maximum, then
 * 					 aborting the packet receive and signaling an error
 * 				  5, receiving the packet
 * 				  6, receiving and checking the CRC. If the CRC is not correct then
 * 					 aborting the packet receive and signaling an error
 * 				  7, Packed receive finished. Disabling the receiver
 *
 * Note:          This is a blocking function and waits until a packet is received or timeout.
  ********************************************************************/

unsigned char com_r04_s01__Receiving_Packet_with_timeout (unsigned char* buffer, unsigned short int* length, unsigned short int timeout)
{
unsigned char d1,d2;
unsigned int len,i,status,k;
unsigned int timeout_counter;

unsigned short int crc_value_r,crc_value_c;

	timeout_counter = timeout*10; /********************************************************/
	com_r04_s01__Enable_Receiver();
	com_r04_s01__Start_Receiving();
	status = com_r04_s01__Read_Status();

/*** waiting for syncron pattern, or time out ***/

	while ( GPIO_14_GET_VALUE() && timeout_counter ) /**************************************/
	{
		timeout_counter--;
		//hal_delay_us(2);
		  for (k = 0; k < CYGNUM_HAL_CPU_SPEED / 1000000 * 2; k++);

	}

	if (timeout_counter <= 0)
		{
//		printf("Timeout = %d",timeout_counter);
		return COM_R04_S01__TIMEOUT;
		}

//	while (GPIO_14_GET_VALUE());
	status = com_r04_s01__Read_Status();
	d1 = com_r04_s01__Read_FIFO();

	while (GPIO_14_GET_VALUE());
	status = com_r04_s01__Read_Status();
	d2 = com_r04_s01__Read_FIFO();

	len = (d1<<8)+d2;

	if (len > *length)
		return COM_R04_S01__ERROR;


	*length = len;

	for (i=0;i<len;i++)
	 {
		while (GPIO_14_GET_VALUE());
		status = com_r04_s01__Read_Status();
	 	buffer[i] = com_r04_s01__Read_FIFO();
	 }

	/*** Receiving CRC ***/
	while (GPIO_14_GET_VALUE());
	status = com_r04_s01__Read_Status();
	d1 = com_r04_s01__Read_FIFO();

	while (GPIO_14_GET_VALUE());
	status = com_r04_s01__Read_Status();
	d2 = com_r04_s01__Read_FIFO();

	crc_value_r = (d1<<8)+d2;
	crc_value_c = crc(buffer,len);

	if (crc_value_r!=crc_value_c)
		return COM_R04_S01__ERROR;

	com_r04_s01__Disable_Receiver();

	return COM_R04_S01__NOERROR;

}





/*********************************************************************/
/*********  CRC  *****************************************************/
/*********************************************************************/


unsigned short CRC_Table[256]=
	{0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
	 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
	 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
	 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
	 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
	 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
	 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
	 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
	 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
	 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
	 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
	 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
	 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
	 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
	 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
	 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
	 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
	 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
	 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
	 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
	 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
	 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
	 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
	 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
	 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
	 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
	 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
	 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
	 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
	 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
	 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
	 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
	};


unsigned short update_crc(unsigned short crc, unsigned char *buf, int len)
{
	unsigned short c=crc^0xFFFF;
	int n;

	for(n=0; n<len; n++)
	{
		c=CRC_Table[(c^buf[n])&0xFF]^(c>>8);
	}

	return c^0xFFFF;
}

unsigned short crc(unsigned char *buf, int len)
{
	return update_crc(0, buf, len);
}

